
#pragma once
#include <AVUIFrameworkElement.h>

namespace AVUI {

class RepeatButton;
class Thumb;

class Track : public FrameworkElement
{
public:

    DECLARE_ELEMENT(Track, FrameworkElement);

    DECLARE_DEPENDENCY_PROPERTY(Minimum);
    float get_Minimum() { return AVUI::UnboxValue<float>(GetValue(get_MinimumProperty())); }
    void set_Minimum(float value) { SetValue(get_MinimumProperty(), AVUI::BoxValue(value)); } 

    DECLARE_DEPENDENCY_PROPERTY(Maximum);
    float get_Maximum() { return AVUI::UnboxValue<float>(GetValue(get_MaximumProperty())); }
    void set_Maximum(float value) { SetValue(get_MaximumProperty(), AVUI::BoxValue(value)); } 

    DECLARE_DEPENDENCY_PROPERTY(Value);
    float get_Value() { return AVUI::UnboxValue<float>(GetValue(get_ValueProperty())); }
    void set_Value(float value) { SetValue(get_ValueProperty(), AVUI::BoxValue(value)); } 

    DECLARE_DEPENDENCY_PROPERTY(ViewportSize);
    float get_ViewportSize() { return AVUI::UnboxValue<float>(GetValue(get_ViewportSizeProperty())); }
    void set_ViewportSize(float value) { SetValue(get_ViewportSizeProperty(), AVUI::BoxValue(value)); } 

    DECLARE_DEPENDENCY_PROPERTY(Density);
    float get_Density() { return AVUI::UnboxValue<float>(GetValue(get_DensityProperty())); }
    void set_Density(float value) { SetValue(get_DensityProperty(), AVUI::BoxValue(value)); } 

    DECLARE_DEPENDENCY_PROPERTY(IsDirectionReversed);
    bool get_IsDirectionReversed() { return AVUI::UnboxValue<bool>(GetValue(get_IsDirectionReversedProperty())); }
    void set_IsDirectionReversed(bool value) { SetValue(get_IsDirectionReversedProperty(), AVUI::BoxValue(value)); } 

    DECLARE_DEPENDENCY_PROPERTY(Orientation);
    Orientation::Enum get_Orientation() { return (Orientation::Enum)(AVUI::UnboxValue<int>(GetValue(get_OrientationProperty()))); }
    void set_Orientation(Orientation::Enum value) { SetValue(get_OrientationProperty(), AVUI::BoxValue<int>(value)); } 

    Track();
    virtual ~Track();

    float ValueFromDistance(float horizontal, float vertical);

    virtual int get_VisualChildrenCount() { return m_cVisualChildren; }
    virtual Visual* GetVisualChild(int idx);

    void set_DecreaseRepeatButton(RepeatButton* pDecreaseRepeatButton);
    RepeatButton* get_DecreaseRepeatButton() { return m_pDecreaseButton; }

    void set_IncreaseRepeatButton(RepeatButton* pIncreaseRepeatButton);
    RepeatButton* get_IncreaseRepeatButton() { return m_pIncreaseButton; }

    void set_Thumb(Thumb* pThumb);
    Thumb* get_Thumb() { return m_pThumb; }


    IMPLEMENT_REFERENCE_PROPERTY(IncreaseRepeatButton, RepeatButton, false);
    IMPLEMENT_REFERENCE_PROPERTY(DecreaseRepeatButton, RepeatButton, false);
    IMPLEMENT_REFERENCE_PROPERTY(Thumb, Thumb, false);

protected:

    Size MeasureOverride(const Size& constraintSize);
    Size ArrangeOverride(const Size& constraintSize);

private:
    static void StaticConstructor();

    void RebuildVisualChildren();

    void InitVisualTree();
    void CoerceLength(float* pComponentLength, float trackLength);
    void ComputeSliderLengths(const Size& arrangeSize, bool isOrientationVertical, float* pDecreaseButtonLength, float* pThumbLength, float* pIncreaseButtonLength);
    bool ComputeScrollBarLengths(const Size& arrangeSize, float viewportSize, bool isOrientationVertical, float* pDecreaseButtonLength, float* pThumbLength, float* pIncreaseButtonLength);

    TRefCountedPtr<RepeatButton> m_pDecreaseButton;
    TRefCountedPtr<RepeatButton> m_pIncreaseButton;
    TRefCountedPtr<Thumb> m_pThumb;

    float m_density;
    float m_thumbCenterOffset;
    bool m_isVisualTreeInitted;
    int m_cVisualChildren;

    static const int mc_TrackVisualChildMax = 3;

    Visual* m_rgVisualChildren[mc_TrackVisualChildMax];
};


}; // namespace AVUI
